﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing;

namespace GT.UI.WinForms
{
    public static partial class Extensions
    {
        public static Control AddControl(this Control host, Control control, int x, int y)
        {
            return host.AddControl(control, new Point(x, y));
        }

        public static Control AddControl(this Control host, Control control, Point location)
        {
            control.Location = location;
            host.Controls.Add(control);
            control.Visible = true;
            return control;
        }

        public static Control AddControl(this Control host, Control control, Control anchor, DockStyle relativeToAnchor, int padding = 0)
        {
            switch (relativeToAnchor)
            {
                case DockStyle.Left:
                    control.Top = anchor.Top;
                    control.Left = anchor.Left - control.Width - padding;
                    break;
                case DockStyle.Right:
                    control.Top = anchor.Top;
                    control.Left = anchor.Right + padding;
                    break;
                case DockStyle.Top:
                    control.Top = anchor.Top - control.Height - padding;
                    control.Left = anchor.Left;
                    break;
                case DockStyle.Bottom:
                    control.Top = anchor.Bottom + padding;
                    control.Left = anchor.Left;
                    break;
            }
            host.Controls.Add(control);
            control.Visible = true;
            return control;
        }

        public static T AddNewControl<T>(this Control host, Control anchor = null, string text = "", DockStyle relativeToAnchor = DockStyle.None, int x = 0, int y = 0, int padding = 0)
            where T : Control, new()
        {
            return AddNewControl<T>(host, anchor, text, relativeToAnchor, new Point(x, y), padding);
        }

        public static T AddNewControl<T>(this Control host, Control anchor = null, string text = "", DockStyle relativeToAnchor = DockStyle.None, Point location = default(Point), int padding = 0)
            where T : Control, new()
        {
            T control = new T();

            if (location == default(Point))
                location = new Point(0, 0);

            if (control is Label)
                control.AutoSize = true;

            control.Name = control.GetType().Name + host.Controls.OfType<T>().Count().ToString();
            control.Text = text;

            if (anchor == null)
            {
                control.Location = location;
                host.Controls.Add(control);
                control.Visible = true;
            }
            else
            {
                control.Anchor = anchor.Anchor;
                switch (relativeToAnchor)
                {
                    case DockStyle.Left:
                        control.Top = anchor.Top + location.Y;
                        control.Left = anchor.Left - control.Width + location.X - padding;
                        if ((anchor.Anchor & AnchorStyles.Left) != 0)
                            control.Anchor &= ~(AnchorStyles.Right);
                        break;
                    case DockStyle.Right:
                        control.Top = anchor.Top + location.Y;
                        control.Left = anchor.Right + location.X + padding;
                        if ((anchor.Anchor & AnchorStyles.Right) != 0)
                            control.Anchor &= ~(AnchorStyles.Left);
                        break;
                    case DockStyle.Top:
                        control.Top = anchor.Top - control.Height + location.Y - padding;
                        control.Left = anchor.Left + location.X;
                        if ((anchor.Anchor & AnchorStyles.Top) != 0)
                            control.Anchor &= ~(AnchorStyles.Bottom);
                        break;
                    case DockStyle.Bottom:
                        control.Top = anchor.Bottom + location.Y + padding;
                        control.Left = anchor.Left + location.X;
                        if ((anchor.Anchor & AnchorStyles.Bottom) != 0)
                            control.Anchor &= ~(AnchorStyles.Top);
                        break;
                }
            }
            host.Controls.Add(control);
            control.Visible = true;
            return control;
        }

        public static Size GetTextSize(this Control control)
        {
            Size ret = new Size(0, 0);
            using (Graphics g = control.CreateGraphics())
            {
                SizeF temp = g.MeasureString(control.Text, control.Font);
                ret.Width = (int)temp.Width;
                ret.Height = (int)temp.Height;
            }
            return ret;
        }

        public static Control SizeToControlArea(this Control control, int paddingRight, int paddingBottom)
        {
            Dictionary<Control, AnchorStyles> anchors = new Dictionary<Control, AnchorStyles>();
            int heightOffset = control.Height - control.ClientSize.Height;
            int widthOffset = control.Width - control.ClientSize.Width;
            var ctrlList = control.Controls.OfType<Control>();
            int width = ctrlList.Max(i => i.Right);
            int height = ctrlList.Max(i => i.Bottom);

            ctrlList = ctrlList.Where(c => c.Anchor != (AnchorStyles.Left | AnchorStyles.Top));
            ctrlList.ForEach(c =>
                {
                    anchors.Add(c, c.Anchor);
                    c.Anchor = AnchorStyles.Top | AnchorStyles.Left;
                });

            control.Height = height + heightOffset + paddingBottom;
            control.Width = width + widthOffset + paddingRight;
            ctrlList.ForEach(c => c.Anchor = anchors[c]);

            return control;
        }

        public static Control SizeToTextArea(this Control control)
        {
            Size size = control.GetTextSize();
            control.Width = size.Width;
            control.Height = size.Height;
            return control;
        }
    }
}
